#include "pen_tool.h"
#include "document.h"

#include "tool_commands.h"

Pen::Pen(QObject* parent): Tool(parent)
{
    m_path = 0;
    m_painterPath = 0;
    m_page = 0;
}

void Pen::mousePressEvent(QMouseEvent* event, Document* document)
{
    // When no page is clicked on, do nothing.
    QPointF position_in_scene = document->mapToScene(event->pos());
    m_page = document->pageAt(position_in_scene);

    if (!m_page) {
        return;
    }

    QPointF position_on_page = m_page->mapFromScene(position_in_scene);
    m_painterPath = new QPainterPath(position_on_page);
    m_path = new QGraphicsPathItem(*m_painterPath, m_page);
    m_path->setPen(*currentPen());
}

void Pen::mouseMoveEvent(QMouseEvent* event, Document* document)
{
    // TODO: Make the path smoother and omit some points from the path?
    if (!m_page) {
        return;
    }

    addPoint(event->pos(), document);
}

void Pen::mouseReleaseEvent(QMouseEvent* event, Document* document)
{
    if (!m_page) {
        return;
    }
    addPoint(event->pos(), document);

    document->pushUndoCommand(new AddGraphicItemCommand(m_page, m_path));
    m_page = 0;
}

void Pen::addPoint(QPoint point, Document *document)
{
    QPointF position_on_page = m_page->mapFromScene(document->mapToScene(point));

    // Make sure the coordinates are within the page and move them there if needed.
    QRectF rect = m_page->drawingRect();

    // Check if the current position is reasonably far away from the last point.
    // Close points are skipped to make the line smoother.
    if ((m_painterPath->currentPosition() - position_on_page).manhattanLength() < Pen::MIN_DISTANCE) {
        return;
    }

    // Keep the path on the page, move the point if necessary.
    if (position_on_page.x() > rect.width()) {
        position_on_page.setX(rect.width());

    } else if (position_on_page.x() < 0) {
        position_on_page.setX(0);
    }

    if (position_on_page.y() > rect.height()) {
        position_on_page.setY(rect.height());

    } else if (position_on_page.y() < 0) {
        position_on_page.setY(0);
    }

    m_painterPath->lineTo(position_on_page);
    m_path->setPath(*m_painterPath);
}
